home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xpaint-2.1.1
/
protocol.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
9KB
|
397 lines
/* +-------------------------------------------------------------------+ */
/* | Copyright 1993, David Koblas (koblas@netcom.com) | */
/* | | */
/* | Permission to use, copy, modify, and to distribute this software | */
/* | and its documentation for any purpose is hereby granted without | */
/* | fee, provided that the above copyright notice appear in all | */
/* | copies and that both that copyright notice and this permission | */
/* | notice appear in supporting documentation. There is no | */
/* | representations about the suitability of this software for | */
/* | any purpose. this software is provided "as is" without express | */
/* | or implied warranty. | */
/* | | */
/* +-------------------------------------------------------------------+ */
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <sys/time.h>
extern XImage *NewXImage(Display*,Visual*,int,int,int);
typedef void (*func_t)(Widget, void *, XEvent *);
typedef struct li_s {
/*
** Destroy request info
*/
void *data;
func_t func;
/*
** Info for watch cursor
*/
int watchCount, computingCount;
Widget shell, parent;
Window win;
Display *dpy;
struct li_s *next;
} LocalInfo;
#define DO_MAP(l) ((l)->watchCount + (l)->computingCount > 0)
#include "bitmaps/wait1.xbm"
#include "bitmaps/wait2.xbm"
#include "bitmaps/wait3.xbm"
#include "bitmaps/wait4.xbm"
static Atom delwin = None, protocols = None;
static LocalInfo *head = NULL;
static int currentCursor = 0;
static Cursor watchCursor = None;
static struct {
Cursor cursor;
int width, height;
unsigned char *bits;
} cursorInfo[] = {
{ None, wait1_width, wait1_height, wait1_bits },
{ None, wait2_width, wait2_height, wait2_bits },
{ None, wait3_width, wait3_height, wait3_bits },
{ None, wait4_width, wait4_height, wait4_bits },
};
static void initCursors(Widget w)
{
static int inited = False;
Display *dpy = XtDisplay(w);
Screen *screen = XtScreen(w);
GC gc = None;
Pixmap pix, mask;
int i, width, height;
XImage *src, *msk;
int x, y;
XColor xcols[2];
if (inited)
return;
inited = True;
xcols[0].pixel = BlackPixelOfScreen(screen);
xcols[1].pixel = WhitePixelOfScreen(screen);
XQueryColors(dpy, DefaultColormapOfScreen(screen), xcols, XtNumber(xcols));
for (i = 0; i < XtNumber(cursorInfo); i++) {
width = cursorInfo[i].width;
height = cursorInfo[i].height;
pix = XCreatePixmapFromBitmapData(dpy, RootWindowOfScreen(screen),
(char*)cursorInfo[i].bits, width, height, True, False, 1);
src = XGetImage(dpy, pix, 0, 0, width, height, AllPlanes, ZPixmap);
msk = NewXImage(dpy, NULL, 1, width, height);
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
Boolean flg = (Boolean)XGetPixel(src, x, y);
if (!flg && x > 0)
flg = XGetPixel(src, x - 1, y);
if (!flg && x < width - 1)
flg = XGetPixel(src, x + 1, y);
if (!flg && y > 0)
flg = XGetPixel(src, x, y - 1);
if (!flg && y < height - 1)
flg = XGetPixel(src, x, y + 1);
XPutPixel(msk, x, y, flg);
}
}
mask = XCreatePixmap(dpy, pix, width, height, 1);
if (gc == None)
gc = XCreateGC(dpy, mask, 0, 0);
XPutImage(dpy, mask, gc, msk, 0, 0, 0, 0, width, height);
XDestroyImage(src);
XDestroyImage(msk);
cursorInfo[i].cursor = XCreatePixmapCursor(dpy, pix, mask,
&xcols[0], &xcols[1], width / 2, height / 2);
XFreePixmap(dpy, pix);
XFreePixmap(dpy, mask);
}
if (gc != None)
XFreeGC(dpy, gc);
}
static void destroyCallback(Widget w, XtPointer data, XtPointer junk)
{
LocalInfo *l = (LocalInfo *)data;
LocalInfo *cur, **pp;
for (cur = *(pp = &head); cur != NULL && cur != l; cur = *(pp = &cur->next));
if (cur == NULL)
return;
*pp = cur->next;
XtFree((XtPointer)data);
}
static void handler(Widget w, XtPointer lArg, XEvent *eventArg, Boolean *junk)
{
XClientMessageEvent *event = (XClientMessageEvent*)eventArg;
LocalInfo *l = (LocalInfo *)lArg;
if (event->type != ClientMessage)
return;
if (event->message_type == protocols && event->data.l[0] == delwin)
l->func(w, l->data, eventArg);
}
static void add(Widget w, LocalInfo *l)
{
unsigned long valuemask;
XSetWindowAttributes attributes;
/*
** Set up the shell destroy info
*/
XtAddRawEventHandler(w, 0, True, handler, (XtPointer)l);
XChangeProperty(XtDisplay(w), XtWindow(w), protocols,
XA_ATOM, 32, PropModeReplace,
(unsigned char *) &delwin, 1);
/*
** Now set up watch cursor information
**
** Ignore device events while the busy cursor is displayed.
*/
valuemask = CWDontPropagate | CWCursor;
attributes.do_not_propagate_mask = (KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
if (watchCursor == None)
watchCursor = XCreateFontCursor(XtDisplay(w), XC_watch);
attributes.cursor = watchCursor;
/*
** The window will be as big as the display screen, and clipped by
** its own parent window, so we never have to worry about resizing
*/
l->win = XCreateWindow(XtDisplay(w), XtWindow(w), 0, 0,
WidthOfScreen(XtScreen(w)), HeightOfScreen(XtScreen(w)),
(unsigned int) 0, 0, InputOnly,
CopyFromParent, valuemask, &attributes);
if (DO_MAP(l))
XMapRaised(l->dpy, l->win);
}
static void realize(Widget w, XtPointer ldataArg, XEvent *event, Boolean *junk)
{
if (event->type == MapNotify) {
XtRemoveEventHandler(w, StructureNotifyMask, False,
realize, ldataArg);
add(w, (LocalInfo*)ldataArg);
}
}
void AddDestroyCallback(Widget w, func_t func, void *data)
{
LocalInfo *l;
if (delwin == None)
delwin = XInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", FALSE);
if (protocols == None)
protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", FALSE);
initCursors(w);
if (delwin == None || protocols == None)
return;
l = XtNew(LocalInfo);
l->data = data;
l->func = func;
l->win = None;
l->dpy = XtDisplay(w);
l->watchCount = 0;
l->computingCount = 0;
l->shell = w;
l->parent = None;
if (!XtIsRealized(w))
XtAddEventHandler(w, StructureNotifyMask, False, realize, (XtPointer)l);
else
add(w, l);
XtAddCallback(w, XtNdestroyCallback, destroyCallback, (XtPointer)l);
l->next = head;
head = l;
}
static Boolean setBusy(LocalInfo *cur, Boolean isWatch, Boolean flag)
{
Boolean doFlush = False;
if (isWatch) {
if (flag) {
cur->watchCount++;
} else {
if (cur->watchCount == 0)
return False;
cur->watchCount--;
}
} else {
if (flag) {
cur->computingCount++;
} else {
if (cur->computingCount == 0)
return False;
cur->computingCount--;
}
}
if (cur->win == None)
return False;
if (cur->watchCount == 0 && cur->computingCount == 0) {
XUnmapWindow(cur->dpy, cur->win);
return False;
}
if (cur->watchCount == 1) {
if (isWatch) {
XMapRaised(cur->dpy, cur->win);
XDefineCursor(cur->dpy, cur->win, watchCursor);
doFlush = True;
}
} else if (cur->computingCount == 1) {
if (!isWatch) {
XMapRaised(cur->dpy, cur->win);
XDefineCursor(cur->dpy, cur->win, cursorInfo[currentCursor].cursor);
doFlush = True;
}
}
return doFlush;
}
void StateSetBusyWatch(Boolean flag)
{
LocalInfo *cur;
Boolean doFlush = False;
for (cur = head; cur != NULL; cur = cur->next)
doFlush |= setBusy(cur, True, flag);
if (doFlush)
XFlush(head->dpy);
}
void StateSetBusy(Boolean flag)
{
LocalInfo *cur;
Boolean doFlush = False;
for (cur = head; cur != NULL; cur = cur->next)
doFlush |= setBusy(cur, False, flag);
if (doFlush)
XFlush(head->dpy);
}
void StateShellBusy(Widget w, Boolean flag)
{
LocalInfo *cur;
Boolean doFlush = False;
if (w == None)
return;
while (!XtIsShell(w))
w = XtParent(w);
for (cur = head; cur != NULL; cur = cur->next) {
if (cur->shell == w) {
doFlush |= setBusy(cur, True, flag);
} else if (cur->parent == w) {
StateShellBusy(cur->shell, flag);
}
}
if (doFlush)
XFlush(head->dpy);
}
void StateAddParent(Widget w, Widget parent)
{
LocalInfo *cur;
if (w == None || parent == None)
return;
while (!XtIsShell(parent))
parent = XtParent(parent);
while (!XtIsShell(w))
w = XtParent(w);
for (cur = head; cur != NULL && cur->shell != w; cur = cur->next)
;
if (cur == NULL)
return;
cur->parent = parent;
}
void StateTimeStep()
{
static Boolean inited = False;
static struct timeval lastTime;
struct timeval nowTime;
Boolean done = False, need = False;
Cursor c;
LocalInfo *cur;
for (cur = head; cur != NULL; cur = cur->next)
if (cur->watchCount == 0 && cur->computingCount != 0 && cur->win != None)
need = True;
if (!need)
return;
gettimeofday(&nowTime, NULL);
if (inited) {
long ds, dus;
dus = nowTime.tv_usec - lastTime.tv_usec;
ds = nowTime.tv_sec - lastTime.tv_sec;
if (dus < 0) {
ds--;
dus += 1000000;
}
if (ds == 0 && dus < 200000)
return;
} else {
inited = True;
}
lastTime = nowTime;
if (++currentCursor == XtNumber(cursorInfo))
currentCursor = 0;
c = cursorInfo[currentCursor].cursor;
for (cur = head; cur != NULL; cur = cur->next) {
if (cur->watchCount == 0 && cur->computingCount != 0 && cur->win != None) {
XDefineCursor(cur->dpy, cur->win, c);
done = True;
}
}
if (done)
XFlush(head->dpy);
}